home *** CD-ROM | disk | FTP | other *** search
- #
- # OK, here's the plan:
- #
- # Tabkey cuts the input line up into edible chunks, and selects a function
- # to do the actual completion. The function will receive a single word as
- # its argument, and return a list of potential matches. The word is whatever
- # is under the cursor, up to the insertion point at the current time. The
- # word may be empty and the function should be able to cope with this.
- #
- # The exact function chosen works like this:
- # * If the current _word_ is a command (first word, begins with $cmdchars),
- # call command_completion by way of parsekey (don't call any aliases).
- # * Or, if the current line is a command, it gets handed to $tabkey.cmd().
- # * Otherwise, call tabkey.default, which is a stub that can be changed
- # to suit your preferences. The default tabkey.default calls
- # tabkey.nickchan which matches against all channels you're currently on
- # and either the nicks in your current channel, or failing that, the
- # nicks in all channels.
- # * tabkey.default is also called if tabkey.cmd() returns nothing. If
- # necessary, the function can prevent this behaviour by returning a single
- # space, but this is discouraged.
- # * tabkey.default is also called by $tabkey.cmd() if it cannot find an
- # appropriate command handler.
- # * $tabkey.cmd() will search for an appropriate function by joining the
- # command and all its arguments together with dots and progressively
- # removing those arguments until a function is found.
- #
- # tabkey "exports" a number of local variables that the functions may use
- # or alter after using "bless":
- # * $curword is what tabkey believes the current word is. The function
- # may make use of this for context sensitivity. I say believes because
- # this may be open to different interpretations.
- # * $wordind is the character index of the _beginning_ of the word that is
- # being completed. If it is equal to $curpos(), then the first argument
- # will be empty and the user has hit tab at the beginning of the word or
- # in between words and the function should return all possible matches.
- # The reason you may need to use it is if the function is designed to
- # complete something that is not a single word. It, and the current
- # cursor position may be altered to cause tabkey to replace the chosen
- # part of the string instead of just the word.
- #
- # The organisation of the supporting functions goes like this:
- # * "Context sensitive" functions are to be named with "tabkey.cmd." as a
- # prefix followed by the name of the command that they are used to
- # complete. This is where tabkey.cmd will look for them.
- # * Generally, completion "methods" should be placed under tabkey.method
- # and shouldn't rely on the exported variables being available, as user
- # supplied functions may forget to re-export them. Context sensitive
- # functions should be as simple as possible.
- #
-
- package tabkey.ce
- bind ^i parse_command tabkey
- alias tabkey.default tabkey.method.nickchan
-
- alias tabkey {
- @ :curword = indextoword($curpos() $L )
- @ :wordind = wordtoindex($curword $L)
- if (32 >= (127 & ascii($mid(${curpos()-1} 1 $L )))) {
- @ curword++
- @ wordind = curpos()
- }
- @ :word = mid($wordind ${curpos()-wordind} $L)
- @ :matches = []
- if (!index($cmdchars $L)) {
- wait for @ matches = tabkey.cmd($word)
- } else {
- wait for @ :matches = tabkey.default($word)
- }
- @ :prefix = prefix($matches)
- if (1 < numwords($matches) && word == prefix) {
- echo Completions for \"$word\": $matches
- } elsif (#matches && strlen($word) <= strlen($prefix)) {
- repeat ${curpos()-wordind} parsekey backspace
- xtype -l $prefix${1<#matches?:[ ]}
- }
- }
-
- alias tabkey.cmd {
- bless
- @ :ret = :cmd = []
- @ :pass = chr($jot($ascii(AZ)))
- @ :pass#= chr($jot($ascii(az)))
- @ :pass#= chr($jot($ascii(09)))
- @ :args = mid(0 $curpos() $L)
- @ :args = unsplit(. $args)
- @ :args = pass(._$pass $args)
- if (!curword) {
- @ ret = tabkey.method.commands($args)
- repeat $#ret {push ret /$shift(ret)}
- return $ret
- }
- while (args) {
- @ :matches = aliasctl(alias pmatch tabkey.cmd.$args*)
- @ :matches = prefix($matches)
- if (aliasctl(alias exists $matches) && matches == [tabkey.cmd.$args]) {
- @ args = matches
- break
- }
- @ args = before(-1 . $args)
- }
- if (args) {
- wait for @ ret = ${args}($*)
- }
- unless (strlen($ret)) {
- wait for @ ret = tabkey.default($*)
- }
- return $ret
- }
-
- # Context sensitive completion goes here.
-
- alias tabkey.cmd.dcc {return $pattern("$0*" CHAT CLOSE CLOSEALL GET LIST RAW RENAME RESUME SEND)}
- alias tabkey.cmd.dcc.resume tabkey.cmd.dcc.send
- alias tabkey.cmd.dcc.send {
- bless
- switch ($curword) {
- (0) {echo This should never happen.;call}
- (1) {echo This should never happen.;call}
- (2) {return $tabkey.method.nick($*)}
- (*) {return $tabkey.method.filei($*)}
- }
- }
-
- alias tabkey.cmd.help {
- bless
- @ :matches = []
- @ :path = restw(1 $left($curpos() $L))
- if (wordind == curpos()) {@ push(path *)}
- @ matches = globi($unsplit(/ $getset(HELP_PATH) $path*))
- repeat $#matches @ push(matches $rightw(1 $remws(/ $split(/ $shift(matches)))))
- return $matches
- }
-
- # Methods.
-
- alias tabkey.method.commands {
- @ :ret = sort($uniq($getcommands($**) $aliasctl(alias match $*) $aliasctl(alias match $**)))
- return $ret
- }
-
- alias tabkey.method.chan { return $pattern("$0*" $mychannels()); }
- alias tabkey.method.notify { return $pattern("$0*" $notify(on)); }
-
- alias alias.foo alias $*;alias $sar(g/globi/glob/$sar(g/filei/file/$*))
- alias.foo tabkey.method.filei {
- @ :f0 = :f1 = globi("$0*")
- while (numwords($f0) == 1 && f0 =~ [*/]) {
- @ f0 = globi($f0*)
- }
- return ${f0 ? f0 : f1}
- }
- alias -alias.foo
-
- alias tabkey.method.nick {
- if (pattern($0* $chanusers())) {
- return $pattern($0* $chanusers());
- } else {
- @ :chanusers = []
- fe ($mychannels()) chan {
- @ push(chanusers $chanusers($chan))
- }
- return $pattern($0* $sort($uniq($chanusers)));
- }
- }
-
- alias tabkey.method.nickchan {
- return $remws(/ $tabkey.method.chan($*) $tabkey.method.nick($*))
- }
-
- alias tabkey.method.nickchannotify {
- return $remws(/ $tabkey.method.chan($*) $sort($uniq($tabkey.method.nick($*) $tabkey.method.notify($*))))
- }
-